package forecasting.validation;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

import forecasting.util.FileUtils;



public class CrossValidationDatasetCreator {

	private static String OUT_TRAIN = "outtrain";
	private static String IN_TRAIN = "intrain";
	private static String OUT_TEST = "outtest";
	private static String IN_TEST = "intest";
	
	/**
	 * Separates a data set into a training set and a testing set using a percentage value.
	 * 
	 * @param inDataset 
	 * @param outDataset
	 * @param percentToTrain  0.0 to 1.0
	 * @param outfileIdentifier the identifier of the begining of the output file names. For example, a file identifer
	 * 		of "set1" will create an input training file with the name of set1_intrain.txt.
	 */
	public static void createCrossValidationDataSet(final String inDataset, 
			final String outDataset, final float percentToTrain, final String outFileIdentifer) {
		
		if (percentToTrain < 0f || percentToTrain > 1.0f) {
			return;
		}
		
		final Scanner inDSScanner = FileUtils.openFileScanner(inDataset);
		final Scanner outDSScanner = FileUtils.openFileScanner(outDataset);
	
		String inHeader = null;
		String outHeader = null;
				
		// Trash the headers
		if (inDSScanner.hasNextLine() && outDSScanner.hasNextLine()) {
			inHeader = inDSScanner.nextLine();
			outHeader = outDSScanner.nextLine();
		}
		
		final List<String> inDSList = FileUtils.scannerToList(inDSScanner);
		final List<String> outDSList = FileUtils.scannerToList(outDSScanner);				
		
		if (inDSList.size() != outDSList.size()) {
			System.out.println("Input Dataset does not match output dataset");
			System.exit(-1);
		}
		
		
		// Create a random seed used to shuffle both of the data sets
		// so they will be shuffled in the same order
		final int seed = new Random().nextInt();
		Collections.shuffle(inDSList, new Random(seed));
		Collections.shuffle(outDSList, new Random(seed));
		
		final int trainingCount = (int) ((float) inDSList.size() * percentToTrain);
						
		PrintWriter inTraining = null;
		PrintWriter outTraining = null;
		PrintWriter inTesting = null;
		PrintWriter outTesting = null;
		
		try {
			inTraining = new PrintWriter(String.format("%s_%s.txt", outFileIdentifer, IN_TRAIN));
			outTraining = new PrintWriter(String.format("%s_%s.txt", outFileIdentifer, OUT_TRAIN));
			inTesting = new PrintWriter(String.format("%s_%s.txt", outFileIdentifer, IN_TEST));
			outTesting = new PrintWriter(String.format("%s_%s.txt", outFileIdentifer, OUT_TEST));
		}  catch (FileNotFoundException e) {
			System.out.println(e);
			e.printStackTrace();
			System.exit(-1);
			return;
		} finally {
			inDSScanner.close();
			outDSScanner.close();			
		}						
		
		inTraining.println(inHeader);
		outTraining.println(outHeader);
		inTesting.println(inHeader);
		outTesting.println(outHeader);
		
		// Create the training files
		for (int i = 0; i < trainingCount; i++) {
			inTraining.println(inDSList.get(i));
			outTraining.println(outDSList.get(i));
		}
				
		// Create the testing files
		for (int i = trainingCount; i < inDSList.size(); i++) {
			inTesting.println(inDSList.get(i));
			outTesting.println(outDSList.get(i));
		}
		
		inTraining.close();
		outTraining.close();
		inTesting.close();
		outTesting.close();		
	}
	
	public static void main(String[] args) {
		if (args.length < 2) {
			System.out.print("You must specify a input and output dataset!");
			System.exit(-1);
		}
		final String inDataset = args[0];
		final String outDataset = args[1];
		
		float trainingPercentage = 0.6f;
		
		if (args.length == 3) {
			trainingPercentage = Float.parseFloat(args[2]);
		}
		
		String fileIdentifier = "set";
		
		if (args.length == 4) {
			fileIdentifier = args[3];
		}
					
		CrossValidationDatasetCreator.createCrossValidationDataSet(inDataset, outDataset, trainingPercentage, fileIdentifier);		
		System.out.println("Cross Validation files created");
	}
}
